

// THIS IS CBC MODE
// original sequential
/// note h = hash(h ^ *d++) is a ALOT SLOWER
// than hash ^= hash(*d++)
#define XORHASH1 \
uint32_t hashStr(const char* data, size_t len) const \
{ \
	const uint8_t* orig = (const uint8_t*) data; \
	const uint32_t* d = (const uint32_t*) data; \
	int leftover = len % 4; \
	int chunks = len / 4; \
	uint32_t h = len; \
	for (int i = 0; i < chunks; ++i) h = hash32(h ^ *d++); \
	if (leftover == 0) return h; \
	orig += len - leftover; \
	uint32_t tmp = 0;\
	switch (leftover) { \
	case 3: tmp = (*orig++) << 8;\
	case 2: tmp = (tmp + *orig++) << 8; \
	case 1: tmp += *orig;\
	}\
	return h ^ hash32(tmp);\
}

// first attempt at parallelization
#define XORHASH \
uint32_t hashStr(const char* data, size_t len) const \
{ \
	const uint8_t* orig = (const uint8_t*) data; \
	const uint32_t* d = (const uint32_t*) data; \
	int leftover = len % 8; \
	int chunks = len / 8; \
	uint32_t a = 0xDEADBEAF + len; \
    uint32_t b = 0; \
	for (int i = 0; i < chunks; i+=2, d+=2) { \
        uint32_t t1 = a, t2 = b; \
		a = hash32(t2 ^ *d);  \
	    b = hash32(t1 ^ *(d+1)); \
	} \
    uint32_t h = a+b; \
	if (leftover == 0) return h; \
	orig += len - leftover; \
    if (leftover >= 4) { \
        h += hash32(*(uint32_t*)(orig)); \
        leftover -= 4; \
        orig += 4; \
    } \
	uint32_t tmp = 0; \
	switch (leftover) { \
    case 4: return h; \
	case 3: tmp = (*orig++) << 8;\
	case 2: tmp = (tmp + *orig++) << 8; \
	case 1: tmp += *orig;\
	}\
	return h ^ hash32(tmp);\
}


// optimized version
//
#define XORHASH3 \
uint32_t hashStr(const char* data, size_t len) const \
{ \
	const uint8_t* orig = (const uint8_t*) data; \
	const uint32_t* d = (const uint32_t*) data; \
	int leftover = len % 8; \
	int chunks = len / 8; \
    const uint32_t* dend = d + chunks; \
	uint32_t h = len; \
    uint32_t a = 0xDEADBEAF;\
    uint32_t b = 0xCAFEBABE; \
    for (const uint32_t* i = d; i < dend; i +=2) { \
		 a = hash32(b ^ *i); \
	     b = hash32(a ^ *(i+1)); \
	} \
	if (leftover == 0) return a+b; \
	orig += len - leftover; \
    if (leftover > 4) {\
        h += hash32(*(uint32_t*)(orig)); \
        leftover -= 4; \
        orig += 4; \
    } \
	uint32_t tmp = 0;\
	switch (leftover) { \
    case 4: return h; \
	case 3: tmp = (*orig++) << 8;\
	case 2: tmp = (tmp + *orig++) << 8; \
	case 1: tmp += *orig;\
	}\
	return a+b+ hash32(tmp);\
}

